const fs = require('fs');
const mapSourceInfo = require('./utils/map-source-info');
// const combineFilePath = require('./utils/combineFilePath');
const readGeneratedFile = require('./utils/readGeneratedFile');
const config = require('./config');
const log4js = require('./utils/log4js');
const clientEndLogger = log4js.clientEndLogger;

/**
 * 使用url读取源码信息
 * @param {*} url
 * @param {*} line
 * @param {*} column
 */
async function mapSourceCodeByUrl(url, line, column) {
	const generatedJsonData = await readGeneratedFile(url);
	const info = await mapSourceInfo(generatedJsonData, line, column);
	return info;
}

/**
 * 解析栈错误
 * @param {*} stack
 * @return {array} stackItemsSourceInfo
 */
async function mapStackSourceInfo(stack) {
	try {
		const stackItems = JSON.parse(stack);
		if (Array.isArray(stackItems) && stackItems.length > 0) {
			const itemsSourceInfo = [];
			for (const item of stackItems) {
				const sourceInfo = await mapSourceCodeByUrl(item.fileurl, item.line, item.column);
				itemsSourceInfo.push(sourceInfo);
			}
			return itemsSourceInfo;
		}
		return [];
	} catch (e) { // parse 错误
		return [];
	}
}


function formatRuntimeErrorLog({
	project, errorInfo, errorStack, message, ip, userAgent, referer
}) {
	const cursor = `${new Array(errorInfo.column).fill(' ').join('')}^`;
	const stackInfo = errorStack.map(item => `    code:${item.code}  file:${item.file} (${item.line}, ${item.column})\r\n`);
	const content = `
  time: ${new Date().toDateString()}
  project: ${project}
  ip: ${ip}
  user-agent: ${userAgent}
  referer: ${referer}
  file: ${errorInfo.file}
  message: ${message}
  line: ${errorInfo.line}
  column: ${errorInfo.column}
  code: ${errorInfo.code}
        ${cursor}
  stack:
  ${stackInfo.join('')}
  ----------------------------------------
  `;
  return content
}

/**
 * 写入加载 script 错误日志
 * @param {*} param0
 */
function formatLoadScriptErrorLog({
	project, request, errorStack, message, ip, userAgent, referer
}) {
	const stackInfo = errorStack.map(item => `    code:${item.code}  file:${item.file} (${item.line}, ${item.column})\r\n`);
	const content = `
  time: ${new Date().toDateString()}
  project: ${project}
  ip: ${ip}
  user-agent: ${userAgent}
  referer: ${referer}
  request: ${request}
  message: ${message}
  stack:
  ${stackInfo.join('')}
  ----------------------------------------
  `;
  return content;
}

/**
 * 
 */
function generateFilePath(dir) {
    const d = new Date();
    const year = d.getFullYear();
    const month = d.getMonth();
    const day = d.getDate();
    return `${dir}/front-${year}-${month}-${day}.log`;
}

/**
 * 记录脚本加载错误;
 */
async function loadScriptError({
	project, request, message, stack, ip, userAgent, referer
}) {
    const errorStackInfo = await mapStackSourceInfo(stack);
    // const filePath = generateFilePath(config.logOutputDir);
	const content = formatLoadScriptErrorLog({
		project,
		request,
		errorStack: errorStackInfo,
		message,
		ip, 
		userAgent,
		referer
	})
	clientEndLogger.error(content);
}

/**
 *  记录运行时错误
 */
async function runtimeError({
	project, fileurl, line, column, message, stack, ip, userAgent ,referer
}) {
	const errorSourceInfo = await mapSourceCodeByUrl(fileurl, line, column);
    const errorStackInfo = await mapStackSourceInfo(stack);
    // const filePath = generateFilePath(config.logOutputDir);
	const content = formatRuntimeErrorLog({
		project,
		errorInfo: errorSourceInfo,
		errorStack: errorStackInfo,
		message,
		ip, 
		userAgent,
		referer
	});
	clientEndLogger.error(content);
}


module.exports = {
	runtimeError,
	loadScriptError,
};

